package com.aviation.sell_ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aviation.sell_ticket.mapper.FlightMapper;
import com.aviation.sell_ticket.pojo.*;
import com.aviation.sell_ticket.service.*;
import com.aviation.sell_ticket.tool.RedisUtil;
import com.aviation.sell_ticket.tool.ResultEnum;
import com.aviation.sell_ticket.tool.ResultUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;


@Service
public class FlightServiceImpl implements FlightService {

    @Resource
    private RedisUtil redis;//引入redis

    @Resource
    RedissonClient redisson;//引入分布式锁

    @Resource
    private FlightMapper flightMapper;//引入FlightMapper

    @Resource
    private FlightService flightService;

    @Resource
    private CityService cityService;//引入cityService

    @Resource
    private AirportService airportService;//引入AirportService

    @Resource
    private FlightPriceService flightPriceService;//引入FlightPriceService

    @Resource
    private ModelService modelService;//引入ModelService

    @Resource
    private ThemeService themeService;

    /**
     * 单程航班
     *
     * @param departure     出发地
     * @param destination   目的地
     * @param departureTime 出发时间
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> oneWayQuery(String departure, String destination, LocalDate departureTime) {
        int solve = 0;
        //获取锁
        RLock rLock = null;
        String flightData;
        try {
            //从redis里提取数据
            flightData = redis.getRedis(departure + "-" + destination + "-" + departureTime);
            //判断数据是否存在
            if (flightData == null) {
                //获取锁
                rLock = redisson.getLock(departure + "-" + destination + "-" + departureTime + "-Lock");
                //设置锁的等待时间与超时时间
                boolean lock = rLock.tryLock(15, 30, TimeUnit.SECONDS);
                //判断是否成功获取锁
                if (lock) {
                    //成功获取锁，结束时需要释放锁
                    solve = 1;
                    //判断数据是否存在
                    if (!redis.isSetRedis(departure + "-" + destination + "-" + departureTime)) {
                        //使用出发地获取城市信息
                        Aviation_city departureCity = cityService.obtainCity(departure);
                        //使用目的地获取城市信息
                        Aviation_city destinationCity = cityService.obtainCity(destination);

                        //是否查询到数据
                        if (departureCity == null || destinationCity == null) {
                            //没有去这个地方的航班
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime, "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }

                        //根据出发地信息获取机场信息
                        List<Aviation_airport> departureAirport = airportService.obtainAirport(departureCity.getCity_id());
                        //根据目的地信息获取机场信息
                        List<Aviation_airport> destinationAirport = airportService.obtainAirport(destinationCity.getCity_id());

                        //是否查询到数据
                        if (departureAirport.size() == 0 || destinationAirport.size() == 0) {
                            //没有去这个地方的航班
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime, "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }

                        //获取符合要求的航班
                        List<Aviation_flight> flights = flightMapper.getFlight(departureAirport, destinationAirport);

                        //判断是否有符合条件的航班
                        if (flights.size() == 0) {
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime, "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }

                        List<Aviation_flight> mark = new ArrayList<>();

                        for (Aviation_flight flight : flights) {
                            //使用航班首次时间与查询时间做计算，算间隔多少天
                            Period next = Period.between(flight.getInitial_time(), departureTime);
                            //判断今日航班是否起飞
                            if (next.getDays() % (flight.getAviation_rotate() + 1) == 0) {
                                //查询价格信息
                                Aviation_flight_price flightPrice = flightPriceService.queryFlightPrices(flight.getFlight_id());
                                if (flightPrice != null) {
                                    //查询航班机型信息
                                    Aviation_model model = modelService.queryModel(flight.getModel_id());
                                    if (model != null) {
                                        //添加机型信息
                                        flight.setModel(model);
                                        //添加价格信息
                                        flight.setFlightPrice(flightPrice);
                                        //计算航班飞行时间
                                        DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                        Duration between = null;
                                        if (flight.getTime_difference() > 0) {
                                            between = Duration.between(LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getDeparture_time().toString()), struct),
                                                    LocalDateTime.parse(timeCorrection(departureTime.plusDays(1).toString() + ' ' + flight.getArrival_time().toString()), struct));
                                        } else {
                                            between = Duration.between(LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getDeparture_time().toString()), struct),
                                                    LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getArrival_time().toString()), struct));
                                        }

                                        Map<String, Integer> dateTime = new HashMap<>();
                                        dateTime.put("hours", Integer.parseInt(String.valueOf(between.toHours())));
                                        dateTime.put("minutes", Integer.parseInt(String.valueOf(between.toMinutes() % 60)));

                                        flight.setTimeOfFlight(dateTime);

                                        //航班起飞与到达时间
                                        Map<String, String> departure_Time = new HashMap<>();
                                        departure_Time.put("departure", departureTime.toString());
                                        if (flight.getTime_difference() > 0)
                                            departure_Time.put("destination", departureTime.plusDays(1).toString());
                                        else departure_Time.put("destination", departureTime.toString());
                                        flight.setDepartureTime(departure_Time);

                                        //填补航班信息
                                        FlightServiceImpl.CompleteFlightInformation(departureCity, destinationCity, departureAirport, destinationAirport, flight);
                                    } else {
                                        //没有找到机型信息，标记此航班信息
                                        mark.add(flight);
                                    }
                                } else {
                                    //没有找到价格信息，标记此航班信息
                                    mark.add(flight);
                                }
                            } else {
                                //标记此航班信息
                                mark.add(flight);
                            }
                        }

                        //删除被标记的航班信息
                        for (Aviation_flight aviation_flight : mark) flights.remove(aviation_flight);

                        //把航班集合转换成JSON
                        JSONArray flightArray = JSONArray.parseArray(JSON.toJSONString(flights));

                        //今日航班存入redis
                        redis.setRidesTime(departure + "-" + destination + "-" + departureTime, flightArray.toJSONString(), (long) 60 * 180, TimeUnit.SECONDS);
                    }
                } else {
                    return ResultUtil.success(ResultEnum.BUSY_SERVICE, null);
                }

            }
        } catch (Exception e) {
            return ResultUtil.beDefeated(ResultEnum.UNKNOWN_ERROR);
        } finally {
            //是锁定状态，并且是当前执行线程的锁，释放锁
            if (solve != 0) {
                if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                    rLock.unlock();
                }
            }
        }
        //如果没有数据则去缓存中提取数据
        if (flightData == null) {
            //查询航班信息
            flightData = redis.getRedis(departure + "-" + destination + "-" + departureTime);
        }

        //判断航班信息是否为空集
        if (flightData.equals("")) {
            return ResultUtil.success(ResultEnum.SUCCESS, null);
        }

        //把航班信息转换为集合
        List<Aviation_flight> flights = JSONArray.parseArray(flightData, Aviation_flight.class);

        //筛选后的航班集合
        List<Aviation_flight> flightScreen = new ArrayList<>();

        LocalDate nowDate = LocalDate.now();
        if (nowDate.isEqual(departureTime)) {
            for (Aviation_flight flight : flights) {
                //获取现在的时间
                LocalTime time = LocalTime.now();
                //判断时间是否大于发机时间
                if (!time.isAfter(flight.getDeparture_time())) {
                    //添加进新的航班集合
                    flightScreen.add(flight);
                }
            }
            //返回航班信息
            return ResultUtil.success(ResultEnum.SUCCESS, flightScreen);
        } else {
            //返回航班信息
            return ResultUtil.success(ResultEnum.SUCCESS, flights);
        }
    }

    /**
     * 航班中转查询
     *
     * @param departure     出发地
     * @param destination   目的地
     * @param departureTime 出发时间
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> transferQuery(String departure, String destination, LocalDate departureTime) {
        int solve = 0;
        //获取锁
        RLock rLock = null;
        String flightData = null;
        JSONArray flights = null;
        try {
            //从redis里提取数据
            flightData = redis.getRedis(departure + "-" + destination + "-" + departureTime + "-Transfer");
            //判断数据是否存在
            if (flightData == null) {
                //获取锁
                rLock = redisson.getLock(departure + "-" + destination + "-" + departureTime + "-Lock-Transfer");
                //设置锁的等待时间与超时时间
                boolean lock = rLock.tryLock(15, 30, TimeUnit.SECONDS);
                //判断是否成功获取锁
                if (lock) {
                    //成功获取锁，结束时需要释放锁
                    solve = 1;
                    //判断数据是否存在
                    if (!redis.isSetRedis(departure + "-" + destination + "-" + departureTime + "-Transfer")) {
                        //使用出发地获取城市信息
                        Aviation_city departureCity = cityService.obtainCity(departure);
                        //使用目的地获取城市信息
                        Aviation_city destinationCity = cityService.obtainCity(destination);

                        //是否查询到数据
                        if (departureCity == null || destinationCity == null) {
                            //没有去这个地方的航班
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime + "-Transfer", "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }

                        //根据出发地信息获取机场信息
                        List<Aviation_airport> departureAirport = airportService.obtainAirport(departureCity.getCity_id());
                        //根据目的地信息获取机场信息
                        List<Aviation_airport> destinationAirport = airportService.obtainAirport(destinationCity.getCity_id());

                        //是否查询到数据
                        if (departureAirport.size() == 0 || destinationAirport.size() == 0) {
                            //没有去这个地方的航班
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime + "-Transfer", "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }

                        //查询支持中转条件的机场
                        List<Integer> transferAirportQuery = flightMapper.transferAirportQuery(departureAirport, destinationAirport);

                        if (transferAirportQuery.size() == 0) {
                            //没有查到中转信息
                            redis.setRidesTime(departure + "-" + destination + "-" + departureTime + "-Transfer", "", (long) 60 * 180, TimeUnit.SECONDS);
                            return ResultUtil.success(ResultEnum.SUCCESS, null);
                        }


                        //创建存储航班信息的JSON数组
                        flights = new JSONArray();

                        for (Integer airport_id : transferAirportQuery) {

                            //根据目的地信息获取机场信息
                            List<Aviation_airport> middleAirport = airportService.middleAirportQuery(airport_id);

                            //没有获取到机场信息，不进行查找航班操作
                            if (middleAirport == null || middleAirport.size() == 0) {
                                continue;
                            }

                            //获取符合要求的出发地航班
                            List<Aviation_flight> departureFlights = flightMapper.getFlight(departureAirport, middleAirport);

                            //获取符合要求的目的地航班
                            List<Aviation_flight> destinationFlights = flightMapper.getFlight(middleAirport, destinationAirport);

                            //获取中转城市信息
                            Aviation_city transferCity = cityService.transferCity(middleAirport.get(0).getCity_id());

                            //当前城市信息丢失
                            if (transferCity == null) {
                                continue;
                            }

                            //筛选出发地航班信息
                            departureFlights = flightService.screenFlight(departureFlights, departureTime, departureCity, transferCity, departureAirport, middleAirport, 1);

                            //筛选目的地航班信息
                            destinationFlights = flightService.screenFlight(destinationFlights, departureTime, transferCity, destinationCity, middleAirport, destinationAirport, 2);

                            //组合航班
                            for (Aviation_flight departureFlight : departureFlights) {
                                //转换时间
                                DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                LocalDateTime departureSetOutTime = LocalDateTime.parse(timeCorrection(departureFlight.getDepartureTime().get("departure") + ' ' + departureFlight.getDeparture_time().toString()), struct);
                                LocalDateTime departureReachTime = LocalDateTime.parse(timeCorrection(departureFlight.getDepartureTime().get("destination") + ' ' + departureFlight.getArrival_time().toString()), struct);

                                //寻找可以组合的航班
                                for (Aviation_flight destinationFlight : destinationFlights) {
                                    //转换时间
                                    LocalDateTime destinationSetOutTime = LocalDateTime.parse(timeCorrection(destinationFlight.getDepartureTime().get("departure") + ' ' + destinationFlight.getDeparture_time().toString()), struct);
                                    LocalDateTime destinationReachTime = LocalDateTime.parse(timeCorrection(destinationFlight.getDepartureTime().get("destination") + ' ' + destinationFlight.getArrival_time().toString()), struct);

                                    //判断中转时间是否充足
                                    Duration between = Duration.between(departureReachTime, destinationSetOutTime);
                                    if (between.toHours() < 1) {
                                        continue;
                                    }

                                    //添加中转所需要等待的时间
                                    Map<String, Integer> dateTime = new HashMap<>();
                                    dateTime.put("hours", Integer.parseInt(String.valueOf(between.toHours())));
                                    dateTime.put("minutes", Integer.parseInt(String.valueOf(between.toMinutes() % 60)));

                                    //重新计算时间
                                    between = Duration.between(departureSetOutTime, destinationReachTime);
                                    //添加行程总共的时间
                                    Map<String, Integer> dateTimeSum = new HashMap<>();
                                    dateTimeSum.put("hours", Integer.parseInt(String.valueOf(between.toHours())));
                                    dateTimeSum.put("minutes", Integer.parseInt(String.valueOf(between.toMinutes() % 60)));

                                    //添加航班跨度，单位天
                                    DateTimeFormatter structTwo = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                                    LocalDate start = LocalDate.parse(departureFlight.getDepartureTime().get("departure"), structTwo);
                                    LocalDate end = LocalDate.parse(destinationFlight.getDepartureTime().get("destination"), structTwo);
                                    Period next = Period.between(start, end);
                                    Map<String, Integer> spanTiem = new HashMap<>();
                                    spanTiem.put("day", Integer.parseInt(String.valueOf(next.getDays())));

                                    //把数据构建成json类型
                                    JSONObject flight = new JSONObject();
                                    flight.put("departureFlight", departureFlight);
                                    flight.put("destinationFlight", destinationFlight);
                                    flight.put("timeDifference", dateTime);
                                    flight.put("timeDifferenceSum", dateTimeSum);
                                    flight.put("spanTiem", spanTiem);

                                    //添加数据进JSON数组
                                    flights.add(flight);
                                }
                            }

                        }

                        //数据存入redis
                        redis.setRidesTime(departure + "-" + destination + "-" + departureTime + "-Transfer", flights.toJSONString(), (long) 60 * 180, TimeUnit.SECONDS);

                    }
                } else {
                    return ResultUtil.success(ResultEnum.BUSY_SERVICE, null);
                }

            }
        } catch (Exception e) {
            return ResultUtil.beDefeated(ResultEnum.UNKNOWN_ERROR);
        } finally {
            //是锁定状态，并且是当前执行线程的锁，释放锁
            if (solve != 0) {
                if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                    rLock.unlock();
                }
            }
        }

        if (flightData == null) {
            if (flights == null) {
                //查询航班信息
                flightData = redis.getRedis(departure + "-" + destination + "-" + departureTime + "-Transfer");
                //判断航班信息是否为空集
                if (flightData.equals("")) {
                    return ResultUtil.success(ResultEnum.SUCCESS, null);
                }
                //转换数据
                flights = JSONArray.parseArray(flightData);
            }
        } else if (flights == null) {
            //判断航班信息是否为空集
            if (flightData.equals("")) {
                return ResultUtil.success(ResultEnum.SUCCESS, null);
            }
            //转换数据
            flights = JSONArray.parseArray(flightData);
        }

        //保存筛选后的航班信息
        JSONArray flightScreen = new JSONArray();

        //获取当前时间
        LocalDateTime nowDate = LocalDateTime.now();

        //信息筛选
        for (Object flight : flights) {
            //提取航班数据
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(flight), JSONObject.class);
            Aviation_flight flightIn = JSON.parseObject(JSON.toJSONString(jsonObject.get("departureFlight")), Aviation_flight.class);
            //转换航班时间
            DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime departureFlightIn = LocalDateTime.parse(timeCorrection(flightIn.getDepartureTime().get("departure") + ' ' + flightIn.getDeparture_time().toString()), struct);

            if (departureFlightIn.isAfter(nowDate)) {
                //添加进新的航班集合
                flightScreen.add(flight);
            }

        }

        //返回航班信息
        return ResultUtil.success(ResultEnum.SUCCESS, flightScreen);

    }

    /**
     * 判断是否需要填补时间
     *
     * @param Time 时间
     * @return String
     */
    public static String timeCorrection(String Time) {
        if (Time.length() < 18) return Time + ":00";
        else return Time;
    }

    /**
     * @param flights            航班信息集合
     * @param departureTime      出发时间
     * @param departureCity      出发地城市信息
     * @param destinationCity    目的地城市信息
     * @param departureAirport   出发地机场集合
     * @param destinationAirport 目的地机场集合
     * @return List<Aviation_flight>
     */
    @Override
    public List<Aviation_flight> screenFlight(List<Aviation_flight> flights, LocalDate departureTime, Aviation_city departureCity, Aviation_city destinationCity, List<Aviation_airport> departureAirport, List<Aviation_airport> destinationAirport, Integer shunt) {

        List<Aviation_flight> flightsTwo = new ArrayList<>();

        for (Aviation_flight flight : flights) {
            for (int i = 0; i < shunt; i++) {
                Aviation_flight standing = flight.clone();
                Aviation_flight flightTwo = flightService.screenFlight(standing, departureTime, departureCity, destinationCity, departureAirport, destinationAirport, i);
                if (flightTwo != null) flightsTwo.add(flightTwo);
            }
        }

        return flightsTwo;
    }

    /**
     * @param shunt              判断此航班是否是第二趟航班
     * @param flight             航班信息
     * @param departureTime      出发时间
     * @param departureCity      出发地城市信息
     * @param destinationCity    目的地城市信息
     * @param departureAirport   出发地机场集合
     * @param destinationAirport 目的地机场集合
     * @return Aviation_flight
     */
    @Override
    public Aviation_flight screenFlight(Aviation_flight flight, LocalDate departureTime, Aviation_city departureCity, Aviation_city destinationCity, List<Aviation_airport> departureAirport, List<Aviation_airport> destinationAirport, Integer shunt) {

        boolean isContinue = false;

        if (shunt == 0) {
            //使用航班首次时间与查询时间做计算，算间隔多少天
            Period next = Period.between(flight.getInitial_time(), departureTime);
            if (next.getDays() % (flight.getAviation_rotate() + 1) == 0) {
                isContinue = true;
            }
        } else {
            departureTime = departureTime.plusDays(1);
            //使用航班首次时间与查询时间做计算，算间隔多少天
            Period next = Period.between(flight.getInitial_time(), departureTime);
            if (next.getDays() % (flight.getAviation_rotate() + 1) == 0) {
                isContinue = true;
            }
        }

        if (isContinue) {

            //查询价格信息
            Aviation_flight_price flightPrice = flightPriceService.queryFlightPrices(flight.getFlight_id());
            if (flightPrice != null) {
                //查询航班机型信息
                Aviation_model model = modelService.queryModel(flight.getModel_id());
                if (model != null) {
                    //添加机型信息
                    flight.setModel(model);
                    //添加价格信息
                    flight.setFlightPrice(flightPrice);

                    //添加航班出发时间
                    Map<String, String> departure_Time = new HashMap<>();
                    departure_Time.put("departure", departureTime.toString());
                    if (flight.getTime_difference() > 0)
                        departure_Time.put("destination", departureTime.plusDays(1).toString());
                    else departure_Time.put("destination", departureTime.toString());
                    flight.setDepartureTime(departure_Time);

                    //计算飞行时间
                    int hours = 0;
                    int minute = 0;
                    if (flight.getTime_difference() > 0) {
                        long intervalTimeSum = ((24 * 3600) - (flight.getDeparture_time().getHour() * 3600 + flight.getDeparture_time().getMinute() * 60)) + (flight.getArrival_time().getHour() * 3600 + flight.getArrival_time().getMinute() * 60);
                        hours = Integer.parseInt(String.valueOf(intervalTimeSum / 3600));
                        minute = Integer.parseInt(String.valueOf(intervalTimeSum % 3600 / 60));
                    } else {
                        long minutesSum = ChronoUnit.MINUTES.between(flight.getDeparture_time(), flight.getArrival_time());
                        hours = Integer.parseInt(String.valueOf(minutesSum / 60));
                        minute = Integer.parseInt(String.valueOf(minutesSum % 60));
                    }
                    //添加飞行时间
                    Map<String, Integer> dateTime = new HashMap<>();
                    dateTime.put("hours", hours);
                    dateTime.put("minutes", minute);
                    flight.setTimeOfFlight(dateTime);
                    //填补航班信息
                    FlightServiceImpl.CompleteFlightInformation(departureCity, destinationCity, departureAirport, destinationAirport, flight);
                } else {
                    //没有找到机型信息，返回null
                    return null;
                }
            } else {
                //没有找到价格信息，返回null
                return null;
            }

            //信息填充完整，返回航班信息
            return flight;
        } else {
            return null;
        }
    }

    /**
     * 判断航班是否今日起飞
     *
     * @param flightId  航班号
     * @param departure 乘机时间
     * @return Boolean
     */
    @Override
    public Aviation_flight verifyRoute(String flightId, LocalDate departure) {
        Aviation_flight flight = flightMapper.verifyRoute(flightId);
        if (null == flight) {
            return null;
        }
        //使用航班首次时间与查询时间做计算，算间隔多少天
        Period next = Period.between(flight.getInitial_time(), departure);
        //判断今日航班是否起飞
        if (next.getDays() % (flight.getAviation_rotate() + 1) == 0) {
            Aviation_flight_price flightPrice = flightPriceService.queryFlightPrices(flight.getFlight_id());
            flight.setFlightPrice(flightPrice);
            //查询航班机型信息
            Aviation_model model = modelService.queryModel(flight.getModel_id());
            flight.setModel(model);
            return flight;
        }
        return null;
    }

    /**
     * 查询单个航班详细信息
     *
     * @param flightId 航班id
     * @return Aviation_flight
     */
    @Override
    public Aviation_flight singleFlight(String flightId, LocalDate departureTime) {
        //查询航班信息
        Aviation_flight flight = flightMapper.verifyRoute(flightId);
        if (null == flight) {
            return null;
        }
        //查询机场详细信息
        List<Aviation_airport> airportSetout = airportService.middleAirportQuery(flight.getAirport_setout());
        List<Aviation_airport> airportArrive = airportService.middleAirportQuery(flight.getAirport_arrive());
        if (airportSetout.size() <= 0 || airportArrive.size() <= 0) {
            return null;
        }
        //添加机场信息
        flight.setSetout_information(airportSetout.get(0));
        flight.setArrive_information(airportArrive.get(0));

        //查询城市信息
        Aviation_city departureCity = cityService.transferCity(airportSetout.get(0).getCity_id());
        Aviation_city destinationCity = cityService.transferCity(airportArrive.get(0).getCity_id());

        if (null == departureCity || null == destinationCity) {
            return null;
        }

        //组合城市信息
        flight.setDepartureCity(departureCity);
        flight.setDestinationCity(destinationCity);

        //查询航班信息
        Aviation_model model = modelService.queryModel(flight.getModel_id());
        if (null == model) {
            return null;
        }
        //添加机型信息
        flight.setModel(model);
        //查询价格信息
        Aviation_flight_price flightPrice = flightPriceService.queryFlightPrices(flightId);
        if (null == flightPrice) {
            return null;
        }
        //添加价格信息
        flight.setFlightPrice(flightPrice);

        //计算航班飞行时间
        DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        Duration between = null;
        if (flight.getTime_difference() > 0) {
            between = Duration.between(LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getDeparture_time().toString()), struct),
                    LocalDateTime.parse(timeCorrection(departureTime.plusDays(1).toString() + ' ' + flight.getArrival_time().toString()), struct));
        } else {
            between = Duration.between(LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getDeparture_time().toString()), struct),
                    LocalDateTime.parse(timeCorrection(departureTime.toString() + ' ' + flight.getArrival_time().toString()), struct));
        }

        Map<String, Integer> dateTime = new HashMap<>();
        dateTime.put("hours", Integer.parseInt(String.valueOf(between.toHours())));
        dateTime.put("minutes", Integer.parseInt(String.valueOf(between.toMinutes() % 60)));

        flight.setTimeOfFlight(dateTime);

        return flight;
    }

    /**
     * 使用航班id查询航班号
     *
     * @param flightId 航班id
     * @return String
     */
    @Override
    public String flightNumber(String flightId) {
        return flightMapper.flightNumber(flightId);
    }

    /**
     * 低价地图获取航班数据
     *
     * @param departure   出发地
     * @param destination 目的地集合
     * @param start       出发时间
     * @param end         返回时间
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> flightMap(String departure, List<String> destination, LocalDate start, LocalDate end) {
        //从redis获取数据
        String flightData = redis.getRedis("Map:" + departure + "/" + Arrays.toString(destination.toArray())+":"+start.toString());
        RLock rLock = null;
        if (null != flightData) {
            return ResultUtil.success(ResultEnum.SUCCESS, JSONArray.parseArray(flightData));
        } else {
            try {
                //获取锁
                rLock = redisson.getLock("Lock:" + departure + "/" + Arrays.toString(destination.toArray()) + "-Lock");
                //设置锁的等待时间与超时时间
                boolean lock = rLock.tryLock(40, 40, TimeUnit.SECONDS);
                if (lock) {
                    //再次判断是否存在数据
                    flightData = redis.getRedis("Map:" + departure + "/" + Arrays.toString(destination.toArray()));
                    if (null != flightData) {
                        return ResultUtil.success(ResultEnum.SUCCESS, JSONObject.parseObject(flightData));
                    }
                    //获取全部城市信息
                    Map<String, Object> cityMap = cityService.getCity();
                    List<Aviation_city> cityList = JSONArray.parseArray(JSON.toJSONString(cityMap.get("data")), Aviation_city.class);
                    if (null == cityList || cityList.size() <= 0) {
                        return ResultUtil.success(ResultEnum.SUCCESS, null);
                    }

                    //获取全部机场信息
                    List<Aviation_airport> airportList = airportService.airportWhole();
                    if (null == airportList || airportList.size() <= 0) {
                        return ResultUtil.success(ResultEnum.SUCCESS, null);
                    }

                    //获取全部主题信息
                    Map<String, Object> themeMap = themeService.wholeTheme();
                    List<Aviation_theme> themeList = JSONArray.parseArray(JSON.toJSONString(themeMap.get("data")), Aviation_theme.class);
                    if (null == themeList || themeList.size() <= 0) {
                        return ResultUtil.success(ResultEnum.SUCCESS, null);
                    }

                    //获取出发地匹配的航班Id
                    List<Integer> departureAirports = filterCities(airportList, departure, cityList);
                    if (null == departureAirports || departureAirports.size() <= 0) {
                        return ResultUtil.success(ResultEnum.SUCCESS, null);
                    }

                    //根据目的地匹配机场ID
                    List<List<Integer>> lists = filterCities(cityList, destination, airportList,themeList);
                    if (lists.size() <= 0) {
                        return ResultUtil.success(ResultEnum.SUCCESS, null);
                    }


                    //创建最终返回数据
                    JSONArray flightMap = new JSONArray();

                    //匹配航班信息
                    for (List<Integer> arrayList : lists) {
                        //根据机场id获取城市信息
                        Aviation_city cityName = obtainCityName(arrayList.get(0), cityList, airportList);
                        if (null == cityName || cityName.getCity_name().equals(departure)) {
                            continue;
                        }

                        List<Aviation_flight> flights = flightMapper.flightMap(departureAirports, arrayList);
                        if (null != flights && flights.size() > 0) {
                            List<Aviation_flight> flightScreening = new ArrayList<>();

                            //取出出发时间与结束时间相匹配的航班信息
                            Period next = Period.between(start, end);
                            flights.forEach(new Consumer<Aviation_flight>() {
                                @Override
                                public void accept(Aviation_flight flight) {
                                    for (int i = 0; i < next.getDays(); i++) {
                                        LocalDate startStanding = start.plusDays(i + 1);
                                        Period nextDate = Period.between(flight.getInitial_time(), startStanding);
                                        if (nextDate.getDays() % (flight.getAviation_rotate() + 1) == 0) {
                                            flight.setDeparture(startStanding);
                                            flightScreening.add(flight);
                                            break;
                                        }
                                        if (startStanding.toString().equals(end.toString())) {
                                            break;
                                        }
                                    }
                                }
                            });

                            //查询最低价的两列航班信息
                            List<Aviation_flight_price> prices = flightPriceService.queryFlightPriceMap(flightScreening);

                            //创建最终航班集合
                            List<Aviation_flight> finalFlightList = new ArrayList<>();
                            //筛选出航班
                            for (Aviation_flight_price price : prices) {
                                for (Aviation_flight flight : flightScreening) {
                                    if (flight.getFlight_id().equals(price.getFlight_id())) {
                                        flight.setFlightPrice(price);
                                        finalFlightList.add(flight);
                                        break;
                                    }
                                }
                            }

                            //添加进最终返回集合
                            JSONObject cityData = new JSONObject();
                            cityData.put("city", cityName);
                            cityData.put("flight", finalFlightList);
                            flightMap.add(cityData);
                        }
                    }

                    //把数据添加进redis
                    redis.setRidesTime("Map:" + departure + "/" + Arrays.toString(destination.toArray())+":"+start.toString(), JSONObject.toJSONString(flightMap), (long) (60 * 60), TimeUnit.SECONDS);
                    return ResultUtil.success(ResultEnum.SUCCESS, flightMap);
                }
            } catch (Exception e) {
                return ResultUtil.beDefeated(ResultEnum.UNKNOWN_ERROR);
            } finally {
                assert rLock != null;
                rLock.unlock();
            }
        }

        return ResultUtil.success(ResultEnum.SUCCESS, null);
    }

    /**
     * 根据机场id返回城市名称
     *
     * @param airportId   机场id
     * @param cityList    城市集合
     * @param airportList 机场集合
     * @return String
     */
    private static Aviation_city obtainCityName(Integer airportId, List<Aviation_city> cityList, List<Aviation_airport> airportList) {
        //获取机场信息
        Aviation_airport airporty = null;
        for (Aviation_airport airport : airportList) {
            if (Objects.equals(airportId, airport.getAirport_id())) {
                airporty = airport;
                break;
            }
        }
        if (null != airporty) {
            //获取城市名称并返回
            for (Aviation_city city : cityList) {
                if (city.getCity_id() == airporty.getCity_id()) {
                    return city;
                }
            }
        }
        return null;
    }

    /**
     * 根据出发地匹配机场信息
     *
     * @param airportList 机场集合
     * @param departure   出发地
     * @param cityList    城市集合
     * @return List<Integer>
     */
    private static List<Integer> filterCities(List<Aviation_airport> airportList, String departure, List<Aviation_city> cityList) {

        //获取出发地完整信息
        Aviation_city city = null;
        for (Aviation_city aviationCity : cityList) {
            if (aviationCity.getCity_name().equals(departure)) {
                city = aviationCity;
                break;
            }
        }

        if (null == city) {
            return null;
        }
        //机场集合
        List<Integer> airportId = new ArrayList<>();

        //根据城市筛选机场信息
        for (Aviation_airport airport : airportList) {
            if (airport.getCity_id() == city.getCity_id()) {
                airportId.add(airport.getAirport_id());
            }
        }
        return airportId;
    }

    /**
     * 根据目的地匹配机场信息
     *
     * @param cityList    城市集合
     * @param destination 目的地集合
     * @param airportList 机场集合
     * @param themeList 主题集合
     * @return List<Aviation_airport>
     */
    private static List<List<Integer>> filterCities(List<Aviation_city> cityList, List<String> destination, List<Aviation_airport> airportList,List<Aviation_theme> themeList) {
        //根据目的地筛选城市
        List<Aviation_city> citys = new ArrayList<>();
        for (String region : destination) {

            boolean themeIs=true;
            //是否是主题
            for (Aviation_theme theme : themeList) {
                if(region.equals(theme.getTheme_name())){
                    String[] cityId = theme.getCity_include().replace("[", "").replace("]","").split(",");
                    for (String id : cityId) {
                        for (Aviation_city city : cityList) {
                            if(city.getCity_id()==Integer.parseInt(id.replace("\"",""))){
                                citys.add(city);
                            }
                        }
                    }
                    themeIs=false;
                    break;
                }
            }

            if(!themeIs){
                continue;
            }

            for (Aviation_city city : cityList) {
                if (region.equals("全中国")) {
                    char charAt = city.getLetter().charAt(0);
                    if (charAt >= 'a' && charAt <= 'z' || charAt >= 'A' && charAt <= 'Z') {
                        citys.add(city);
                    }
                } else if (region.equals("美洲") || region.equals("非洲") || region.equals("大洋洲") || region.equals("欧洲") || region.equals("亚洲")) {
                    if (city.getSuperior().equals(region)) {
                        citys.add(city);
                    }
                } else {
                    if (city.getCity_name().equals(region)) {
                        citys.add(city);
                        break;
                    }
                }
            }
        }

        //去除重复城市
        cityList = citys.stream().distinct().collect(Collectors.toList());

        //机场集合
        List<List<Integer>> airports = new ArrayList<>();

        //根据城市筛选机场信息
        for (Aviation_city city : cityList) {
            List<Integer> airportId = new ArrayList<>();
            for (Aviation_airport airport : airportList) {
                if (airport.getCity_id() == city.getCity_id()) {
                    airportId.add(airport.getAirport_id());
                }
            }
            if (airportId.size() > 0) {
                airports.add(airportId);
            }
        }

        return airports;
    }

    /**
     * 填补完整的航班信息
     *
     * @param departureCity      出发地城市信息
     * @param destinationCity    目的地城市信息
     * @param departureAirport   出发地机场集合
     * @param destinationAirport 目的地机场集合
     * @param flight             航班信息
     */
    private static void CompleteFlightInformation(Aviation_city departureCity, Aviation_city destinationCity, List<Aviation_airport> departureAirport, List<Aviation_airport> destinationAirport, Aviation_flight flight) {
        //添加出发地城市信息
        flight.setDepartureCity(departureCity);
        //添加目的地城市信息
        flight.setDestinationCity(destinationCity);
        //添加出发地机场信息
        flight.setSetout_information(FlightServiceImpl.screenAirport(departureAirport, flight.getAirport_setout()));
        //添加目的地机场信息
        flight.setArrive_information(FlightServiceImpl.screenAirport(destinationAirport, flight.getAirport_arrive()));
        //抹除关键信息
        flight.setInitial_time(null);
    }

    /**
     * 筛选出符合条件的机场
     *
     * @param Airports  机场集合
     * @param airportId 机场id
     * @return Aviation_airport
     */
    private static Aviation_airport screenAirport(List<Aviation_airport> Airports, Integer airportId) {
        //如果只有一个机场信息，那么返回这一个机场信息
        if (Airports.size() <= 1) {
            return Airports.get(0);
        }
        //构建一个空的机场类
        Aviation_airport Airport = null;
        //开始遍历机场集合
        for (Aviation_airport airport : Airports) {
            //比较机场id
            if (Objects.equals(airportId, airport.getAirport_id())) {
                //复制给机场类
                Airport = airport;
                break;
            }
        }
        //返回找到的机场信息
        return Airport;
    }
}
